/**
 * FileName: RsaCipherHelper
 * Author:   win7
 * Date:     2018/11/28 19:01
 * Description: RsaCipherHelper
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.cssw.fyzb.tps.third.tf56pay.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import java.util.SortedMap;

/**
 * 〈一句话功能简述〉<br>
 * 〈RsaCipherHelper 〉
 *
 * @author z.z.hu
 * @create 2018/11/28
 * @since 1.0.0
 */
public class RsaCipherHelper {
    /**
     * 生成签名
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static String sign(String content, String privateKey) {
        return sign(content, str2PrivateKey(privateKey));
    }

    /**
     * 验证签名
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static boolean verify(String content, String sign, String publicKey) {
        return verify(content, sign, str2PublicKey(publicKey));
    }

    /**
     * @param content
     * @param privateKey
     * @return
     */
    public static String sign(String content, RSAPrivateKey privateKey) {
        try {
            Signature signature = Signature.getInstance("SHA1withRSA");
            signature.initSign(privateKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            return new BASE64Encoder().encode(signature.sign());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param content
     * @param publicKey
     * @return
     */
    public static boolean verify(String content, String sign, RSAPublicKey publicKey) {
        try {
            Signature signature = Signature.getInstance("SHA1withRSA");
            signature.initVerify(publicKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            return signature.verify((new BASE64Decoder()).decodeBuffer(sign));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static RSAPublicKey str2PublicKey(String publicKeyPerm) {
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec((new BASE64Decoder()).decodeBuffer(publicKeyPerm));
            KeyFactory keyFactory = KeyFactory.getInstance("ItrusRSA");
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static RSAPrivateKey str2PrivateKey(String privateKeyPerm) {
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(privateKeyPerm));
            KeyFactory keyFactory = KeyFactory.getInstance("ItrusRSA");
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将所有POST 参数（sign除外）进行字典排序，组成字符串, 然后使用私钥产生签名
     *
     * @param params
     * @return itrusRSASign
     */
    public static String encodeParams(SortedMap<?, ?> params, String privateKey) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<?, ?> entry : params.entrySet()) {
            sb.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("&");
        }

        sb.deleteCharAt(sb.length() - 1);
        return sign(sb.toString(), privateKey);
    }

    public static void generateRsaKey() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ItrusRSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.genKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            BASE64Encoder base64Encoder = new BASE64Encoder();
            System.out.println("-------------------public key----------------------");
            System.out.println(base64Encoder.encode(publicKey.getEncoded()));
            System.out.println("-------------------private key---------------------");
            System.out.println(base64Encoder.encode(privateKey.getEncoded()));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}